Implement
ReplaceAll<S, From, To>
which replace the all the substringFrom
withTo
in the given stringS
實作 ReplaceAll<S, From, To>
,其功能是在給定的字串 S
中,將所有子字串 From 替換為 To
。
type replaced = ReplaceAll<'t y p e s', ' ', ''> // expected to be 'types'
接下來,你的任務是讓下面的type cases測試通過:
type cases = [
Expect<Equal<ReplaceAll<'foobar', 'bar', 'foo'>, 'foofoo'>>,
Expect<Equal<ReplaceAll<'foobar', 'bag', 'foo'>, 'foobar'>>,
Expect<Equal<ReplaceAll<'foobarbar', 'bar', 'foo'>, 'foofoofoo'>>,
Expect<Equal<ReplaceAll<'t y p e s', ' ', ''>, 'types'>>,
Expect<Equal<ReplaceAll<'foobarbar', '', 'foo'>, 'foobarbar'>>,
Expect<Equal<ReplaceAll<'barfoo', 'bar', 'foo'>, 'foofoo'>>,
Expect<Equal<ReplaceAll<'foobarfoobar', 'ob', 'b'>, 'fobarfobar'>>,
Expect<Equal<ReplaceAll<'foboorfoboar', 'bo', 'b'>, 'foborfobar'>>,
Expect<Equal<ReplaceAll<'', '', ''>, ''>>,
]
從以下幾個方向來思考:
替換判斷 (Replacement Check): 首先確認 From
是否為空字串。如果是,則返回原字串 S
,因為無法進行任何替換。
字串拆解 (String Decomposition): 利用 TypeScript 的模板字串語法 (Template literals),將字串 S
拆分為三個部分:F
(替換前的部分)、From
(要替換的部分)和 R
(替換後的部分)。
執行替換 (Perform Replacement): 如果在 S
中找到 From
,則將其替換為 To
,並組合成新的字串。如果未找到,則返回原字串 S
。
遞迴實現 (Recursive Implementation): 使用遞迴方式逐步掃描 S
,每次找到匹配的 From
後進行替換,再對剩下的部分 R
重複相同的過程,直到掃描整個字串。
邊界情況考量 (Consider Edge Cases): 在實作過程中,確保考慮到如果 From
不存在於 S
中,結果應該保持不變。
解法:
type Replace<S extends string, From extends string, To extends string> = From extends ''
? S
: S extends `${infer F}${From}${infer R}`
? `${F}${To}${R}`
: S;
細節分析:
條件型別 (Conditional Type): ReplaceAll<S>
是一個條件型別,使用模板字面型別來分解字串 S
。它檢查 From
是否為空字串,若是,則直接返回原字串 S
。
字串結構檢查 (String Structure Check): 當 S
符合格式 ${infer F}${From}${infer R}
時,infer F
提取出 From
前的部分,而 infer R
則捕捉 From
後剩餘的所有字符。
遞迴替換 (Recursive Replacement): 當找到符合的 From
時,將其替換為 To
,並對剩下的部分 R
遞迴地繼續替換。這樣能確保所有的 From
都被替換。
保持不變 (Maintain Originality): 如果 From
沒有出現在 S
中,則返回原字串 S
,確保只有在實際找到匹配時才進行替換。這樣的設計使得其他部分保持不變,僅進行指定的替換操作。
這樣,我們就能順利通過測試啦 🎉 😭 🎉
本次介紹了 ReplaceAll
的實作,下一關會挑戰 Append Argument
,期待再相見!